from re import X
import numpy as np
import easynn as nn

# Create a numpy array of 10 rows and 5 columns.
# Set the element at row i and column j to be i+j.
def Q1():
    rqshan_temp1 = np.array(range(10)).reshape(-1, 1)
    rqshan_temp2 = np.array(range(5)).reshape(1, -1)

    rqshan_temp = rqshan_temp1 + rqshan_temp2

    return rqshan_temp

# Add two numpy arrays together.
def Q2(a, b):
    rqshan_temp = a + b
    return rqshan_temp

# Multiply two 2D numpy arrays using matrix multiplication.
def Q3(a, b):
    rqshan_temp = a.dot(b)
    return rqshan_temp

# For each row of a 2D numpy array, find the column index
# with the maximum element. Return all these column indices.
def Q4(a):
    rqshan_temp = np.argmax(a, axis=1)
    return rqshan_temp

# Solve Ax = b.
def Q5(A, b):
    rqshan_temp = np.linalg.solve(A, b)
    return rqshan_temp

# Return an EasyNN expression for a+b.
def Q6():
    rqshan_temp = nn.Input('a') + nn.Input('b')
    return rqshan_temp

# Return an EasyNN expression for a+b*c.
def Q7():
    rqshan_temp = nn.Input('a') + nn.Input('b') * nn.Input('c')
    return rqshan_temp

# Given A and b, return an EasyNN expression for Ax+b.
def Q8(A, b):
    rqshan_temp = nn.Const(A) * nn.Input('x') + nn.Const(b)
    return rqshan_temp

# Given n, return an EasyNN expression for x**n.
def Q9(n):
    rqshan_temp = nn.Input('x')
    rqshan_final = nn.Const(1)

    while n:
        if n & 1:
            rqshan_final = rqshan_final * rqshan_temp

        rqshan_temp = rqshan_temp * rqshan_temp
        n >>= 1        

    return rqshan_final

# Return an EasyNN expression to compute
# the element-wise absolute value |x|.
def Q10():
    rqshan_temp = nn.Input('x')
    rqshan_value = nn.ReLU()
    rqshan_temp1 = rqshan_value(rqshan_temp)
    rqshan_temp2 = rqshan_value(-rqshan_temp)

    rqshan_total = rqshan_temp1 + rqshan_temp2
    return rqshan_total
